package com.tool.app.util.json.databind;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
import com.fasterxml.jackson.databind.exc.InvalidFormatException;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;

/**
 * 自定义 LocalDateTime 反序列化器。
 * 支持字段上的 @JsonFormat 注解指定日期格式；
 * 如果没有注解，则支持：
 * - 时间戳（long）
 * - 默认 ISO 格式字符串（如 "2025-05-28T14:30:00"）
 */
public class CustomLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> implements ContextualDeserializer {

    /**
     * 默认用于解析的日期时间格式。
     */
    private static final DateTimeFormatter DEFAULT_FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE_TIME;

    /**
     * 用户指定的日期格式解析器，null 表示使用默认格式。
     */
    private final DateTimeFormatter formatter;

    public CustomLocalDateTimeDeserializer() {
        this(null);
    }

    public CustomLocalDateTimeDeserializer(DateTimeFormatter formatter) {
        this.formatter = formatter;
    }

    @Override
    public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        try {
            if (p.hasToken(JsonToken.VALUE_NUMBER_INT)) {
                // 处理时间戳（毫秒）
                return LocalDateTime.ofEpochSecond(p.getLongValue() / 1000, 0, java.time.ZoneOffset.UTC);
            } else if (p.hasToken(JsonToken.VALUE_STRING)) {
                // 处理字符串
                String text = p.getText().trim();
                if (text.isEmpty()) {
                    return null; // 空字符串返回 null
                }
                if (formatter != null) {
                    // 先尝试用户指定的格式
                    return LocalDateTime.parse(text, formatter);
                } else {
                    // 没有指定格式，直接使用默认格式
                    return LocalDateTime.parse(text, DEFAULT_FORMATTER);
                }
            } else {
                throw InvalidFormatException.from(p, "Unsupported token type for LocalDateTime: " + p.getCurrentToken(), null, LocalDateTime.class);
            }
        } catch (DateTimeParseException e) {
            throw InvalidFormatException.from(p, String.format("Failed to parse LocalDateTime value: '%s'. Reason: %s", p.getText(), e.getMessage()), null, LocalDateTime.class);
        } catch (Exception e) {
            throw InvalidFormatException.from(p, "Unexpected error during LocalDateTime deserialization", null, LocalDateTime.class);
        }
    }
    @Override
    public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) {
        if (property == null) {
            return this;
        }

        JsonFormat annotation = property.getMember().getAnnotation(JsonFormat.class);
        if (annotation == null || annotation.pattern().isEmpty()) {
            return this;
        }

        try {
            DateTimeFormatter fieldFormatter = DateTimeFormatter.ofPattern(annotation.pattern());
            return new CustomLocalDateTimeDeserializer(fieldFormatter);
        } catch (IllegalArgumentException | DateTimeParseException e) {
            throw new IllegalArgumentException("Invalid date format pattern '" + annotation.pattern() + "' on field: " + property.getName(), e);
        }
    }
}